#include "TcpServer.hpp"
#include "Socket.hpp"
#include "Util.hpp"
#include <memory>
#include <string>
#include <unordered_map>
#include <iostream>
#include <sstream>

const std::string space = " ";
const std::string endline = "\r\n";
const std::string resp = ": ";

const std::string webroot = "./wwwroot";
const std::string homepage = "/index.html";
const std::string page_404 = "/404.html";

class HttpRequest
{
public:
    // std::string Serialize()
    // {

    // }

    void ParseReqLine(const std::string& s)
    {
        std::stringstream ss(s);
        ss >> _method >> _uri >> _version;
    }

    void Deserialize(std::string& reqstr)
    {
        //获取请求行
        std::string reqline;
        Util::ReadOneLine(reqstr, reqline, endline);

        //对请求行进行反序列化
        ParseReqLine(reqline);

        if(_uri == "/") _uri = webroot + homepage;
        else _uri = webroot + _uri;

        //提取参数
        size_t pos = _uri.find('?');
        if(pos == std::string::npos)
        return;

        _args = _uri.substr(pos + 1);
        _uri = _uri.substr(0, pos);
        _isexec = true;
    }

    std::string Uri()
    {
        return _uri;
    }

    bool Isexec()
    {
        return _isexec;
    }

    std::string Args()
    {
        return _args;
    }
private:
    std::string _method; // 请求方法
    std::string _uri; // 资源路径
    std::string _version; // 版本
    std::unordered_map<std::string, std::string> _headers; // 报头
    std::string _blankline = endline; // 空行
    std::string _text; // 正文

    std::string _args; // 参数
    bool _isexec = false; // 是否要交互
};

class HttpResponse
{
public:
    std::string Serialize()
    {
        std::string repstr = _version + space + std::to_string(_code) + space + _desc + endline;
        for(auto& header : _headers)
        {
            repstr += header.first + resp + header.second + endline;
        }
        repstr += _blankline;
        repstr += _text;
        return repstr;
    }

    void SetTargetFile(const std::string& target)
    {
        _targetfile = target;
    }

    void SetCode(int code)
    {
        switch (code)
        {
        case 200:
            _code = 200;
            _desc = "OK";
            break;
        case 404:
            _code = 404;
            _desc = "Not Found";
            break;
        default:
            break;
        }
    }

    void SetHeader(const std::string key, const std::string value)
    {
        if(_headers.find(key) != _headers.end()) return; // 如果有就不插入
        _headers[key] = value;
    }

    std::string Uri2Suffix()
    {
        auto pos = _targetfile.rfind('.');
        if(pos != std::string::npos)
        {
            std::string suffix = _targetfile.substr(pos + 1);

            if(suffix == "html" || suffix == "htm") return "text/html";
            else if(suffix == "jpg") return "image/jpeg";
            else if(suffix == "png") return "image/png";
        }
        return "";
    }

    void SetText(const std::string& text)
    {
        _text = text;
    }

    //构建应答
    void MakeResponse()
    {
        ssize_t filesize = 0;
        //读取网页资源
        if(!Util::ReadFileContent(_targetfile, _text))
        {
            LOG(LogLevel::WARING) << "客户端获取" << _targetfile << "但不存在";
            SetCode(404);
            //重新读取页面 -- 404页面
            _targetfile = webroot + page_404;
            Util::ReadFileContent(_targetfile, _text);
        }
        else
        {
            SetCode(200);
        }
        filesize = Util::FileSize(_targetfile);
        SetHeader("Content_Length", std::to_string(filesize));

        std::string suffix = Uri2Suffix();
        if(suffix != "")
        {
            SetHeader("Content_Type", suffix);
        }
    }

    // void Deserialize(const std::string& reqstr)
    // {

    // }
private:
    std::string _version = "HTTP/1.1"; // 版本
    int _code; // 状态码
    std::string _desc; // 状态码描述
    std::unordered_map<std::string, std::string> _headers; // 报头
    std::string _blankline = endline; // 空行
    std::string _text;  // 正文

    std::string _targetfile; // 目标页面
};

typedef std::function<void(HttpRequest&, HttpResponse&)> http_func_t;

class Http
{
public:
    Http(uint16_t port) : tsvr(std::make_unique<TcpServer>(port))
    {}

    void HalderHttpRequest(std::shared_ptr<Socket>& sock, InetAddr& client)
    {
        std::string reqstr;
        int n = sock->Recv(reqstr);
        if(n > 0)
        {
            //反序列化
            HttpRequest req;
            req.Deserialize(reqstr);

            //判断是否需要交互
            if(req.Isexec())
            {
                HttpResponse rep;
                _route[req.Uri()](req, rep); // 回调对应的交互函数
                std::string repstr = rep.Serialize();
                sock->Send(repstr);
            }
            else
            {
                //构建应答
                HttpResponse rep;
                rep.SetTargetFile(req.Uri());
                rep.MakeResponse();

                //序列化应答
                std::string repstr = rep.Serialize();
                sock->Send(repstr);
            }
        }
    }

    void Start()
    {
        tsvr->Start([this](std::shared_ptr<Socket>& sock, InetAddr& client)
        {
            this->HalderHttpRequest(sock, client);
        });
    }

    void RegisterService(const std::string& s, http_func_t func)
    {
        std::string key = webroot + s;
        if(_route.find(s) != _route.end()) return;
        _route[key] = func;
    }
private:
    std::unique_ptr<TcpServer> tsvr;
    std::unordered_map<std::string, http_func_t> _route;
};